<!--

/*
* Copyright (C) 2005-2013 University of Sydney
*
* Licensed under the GNU License, Version 3.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.gnu.org/licenses/gpl-3.0.txt
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/

/**
* brief description of file
*
* @author      Tom Murtagh
* @author      Kim Jackson
* @author      Ian Johnson   <ian.johnson@sydney.edu.au>
* @author      Stephen White   <stephen.white@sydney.edu.au>
* @author      Artem Osmakov   <artem.osmakov@sydney.edu.au>
* @copyright   (C) 2005-2013 University of Sydney
* @link        http://Sydney.edu.au/Heurist
* @version     3.1.0
* @license     http://www.gnu.org/licenses/gpl-3.0.txt GNU License 3.0
* @package     Heurist academic knowledge management system
* @subpackage  !!!subpackagename for file such as Administration, Search, Edit, Application, Library
*/

-->
<!--

/**
 * filename, brief description, date of creation, by whom
 * @copyright (C) 2005-2010 University of Sydney Digital Innovation Unit.
 * @link: http://HeuristScholar.org
 * @license http://www.gnu.org/licenses/gpl-3.0.txt
 * @package Heurist academic knowledge management system
 * @todo
 **/

-->
<html>
<head><title>Google Maps digitiser</title></head>

<body>

<style>
div.circle, div.rectangle, div.polygon {
	position: absolute;
}
div.point div {
	width: 3px; height: 3px;
	background-color: blue;
	position: relative;
	left: 1px; top: 1px;
	line-height: 3px;
}
div.point {
	position: absolute;
	width: 3px; height: 3px;

	background-color: white;
	z-index: 0;
}
div.circle div.centre-point {
	position: absolute;
	width: 3px; height: 3px;

	background-color: red;
	z-index: 1;
}
div.polygon div.roving-point {
	position: absolute;
	width: 3px; height: 3px;
	background-color: black;
	z-index: 1;
}
div.polygon div.roving-point div {
	width: 3px; height: 3px;
	background-color: yellow;
	position: relative;
	left: 1px; top: 1px;
	line-height: 3px;
}

</style>


<script>

var Shape = function() {
	this.div = document.body.appendChild(document.createElement("div"));
	this.points = [];
};
Shape.prototype.startResize = function() {
	var thisRef = this;
	this.onclickClosure = function(e) { thisRef.onclick.call(thisRef, e); };
	this.onmousemoveClosure = function(e) { thisRef.onmousemove.call(thisRef, e); };
	// have to delay the setting of the onclick handler, otherwise IE can use it right awawy
	setTimeout(function() { top.HEURIST.registerEvent(document, "click", thisRef.onclickClosure, true); }, 0);
	top.HEURIST.registerEvent(document, "mousemove", this.onmousemoveClosure, true);
};
Shape.prototype.onclick = function(e) {
	top.HEURIST.deregisterEvent(document, "click", this.onclickClosure, true);
	top.HEURIST.deregisterEvent(document, "mousemove", this.onmousemoveClosure, true);
};
Shape.prototype.allocatePoints = function(nPoints) {
	if (this.points.length > nPoints) {
		// hide unnecessary points
		for (var i=nPoints; i < this.points.length; ++i) {
			this.points[i].style.display = "none";
		}
	}
	else if (this.points.length < nPoints) {
		// create new points
		for (var i=this.points.length; i < nPoints; ++i) {
			this.points[i] = this.div.appendChild(document.createElement("div"));
			this.points[i].appendChild(document.createElement("div"));
				this.points[i].firstChild.appendChild(document.createElement("span"));
			this.points[i].className = "point";
		}
	}
};


var Circle = function(x, y, radius) {
	Shape.call(this);

	this.radius = (radius && radius > 0)? radius : 0;
	this.x = x;
	this.y = y;

	this.div.className = "circle";
	this.centrePoint = this.div.appendChild(document.createElement("div"));
		this.centrePoint.className = "centre-point";
	this.centrePoint.appendChild(document.createElement("div"));
		this.centrePoint.firstChild.appendChild(document.createElement("span"));
	this.redraw();

	this.startResize();
};
Circle.prototype = new Shape;
Circle.prototype.setRadius = function(radius) {
	this.radius = radius;
	this.redraw();
};
Circle.prototype.onmousemove = function(e) {
	var pos = top.HEURIST.util.getEventPosition(e || window.event);
	var newRadius = Math.sqrt((pos.x - this.x)*(pos.x - this.x) + (pos.y - this.y)*(pos.y - this.y));

	if (Math.abs(newRadius - this.radius) >= 2)
		this.setRadius(newRadius);
};
Circle.prototype.redraw = function() {
	// work out how many points we need to represent the circle at this radius
	var nPoints = 4 << Math.floor(Math.log(this.radius / 20) / Math.log(2));
	this.allocatePoints(nPoints);

	this.div.style.left = (this.x - this.radius) + "px";
	this.div.style.top = (this.y - this.radius) + "px";

	// Position the points
	this.centrePoint.style.left = this.radius + "px";
	this.centrePoint.style.top = this.radius + "px";

	var offsetX = -Math.floor(this.points[0].offsetWidth / 2);
	var offsetY = -Math.floor(this.points[0].offsetHeight / 2);
	for (var i=0; i < nPoints; ++i) {
		var x = Math.floor(this.radius * (1 + Math.sin(2*Math.PI * i / nPoints)));
		var y = Math.floor(this.radius * (1 + Math.cos(2*Math.PI * i / nPoints)));

		this.points[i].style.left = x + "px";
		this.points[i].style.top = y + "px";
		this.points[i].style.display = "";
	}
};


var Rectangle = function(x1, y1, x2, y2) {
	Shape.call(this);

	this.x1 = x1;
	this.x2 = x2;
	this.y1 = y1;
	this.y2 = y2;

	this.div.className = "rectangle";
	this.redraw();

	this.startResize();
}
Rectangle.prototype = new Shape;
Rectangle.prototype.setPoint2 = function(x2, y2) {
	this.x2 = x2;
	this.y2 = y2;
	this.redraw();
};
Rectangle.prototype.onmousemove = function(e) {
	var pos = top.HEURIST.util.getEventPosition(e || window.event);

	if (this.x2 != pos.x  ||  this.y2 != pos.y)
		this.setPoint2(pos.x, pos.y);
};
Rectangle.prototype.redraw = function() {
	var nPoints = 4 << Math.floor(Math.log((Math.abs(this.x1 - this.x2) + Math.abs(this.y1 - this.y2)) / 40) / Math.log(2));
	this.allocatePoints(nPoints);

	this.div.style.left = Math.min(this.x1, this.x2) + "px";
	this.div.style.top = Math.min(this.y1, this.y2) + "px";

	var pointsPerSide = nPoints / 4;
	var width = this.x2 - this.x1;
	var height = this.y2 - this.y1;
	for (var i=0; i < pointsPerSide; ++i) {
		var x = Math.round(width * i / pointsPerSide);
		var y = Math.round(height * i / pointsPerSide);

		this.points[i*4].style.left = x + "px";
		this.points[i*4].style.top = 0;
		this.points[i*4 + 1].style.left = (width - x) + "px";
		this.points[i*4 + 1].style.top = height + "px";

		this.points[i*4 + 2].style.top = y + "px";
		this.points[i*4 + 2].style.left = width + "px";
		this.points[i*4 + 3].style.top = (height - y) + "px";
		this.points[i*4 + 3].style.left = 0;
	}

	for (var i=0; i < nPoints; ++i)
		this.points[i].style.display = "";
};


var Polygon = function(x, y) {
	Shape.call(this);

	this.vertices = [ { x: x, y: y } ];
	this.newVertex = { x: x, y: y };

	this.div.className = "polygon";
	this.redraw();

	this.awaitNextVertex();
};
Polygon.prototype = new Shape;
Polygon.prototype.addNewVertex = function() {
	this.newVertex.drawn = false;
	this.vertices.push(this.newVertex);
	this.newVertex = { x: this.newVertex.x, y: this.newVertex.y };
	this.redraw();
};
Polygon.prototype.addFinalVertex = function() {
	this.newVertex.drawn = false;
	this.vertices.push(this.newVertex);
	this.newVertex = null;
	this.redraw();
};
Polygon.prototype.onmousemove = function(e) {
	var pos = top.HEURIST.util.getEventPosition(e || window.event);

	if (Math.abs(this.newVertex.x - pos.x) + Math.abs(this.newVertex.y - pos.y) >= 2) {
		this.newVertex.x = pos.x;
		this.newVertex.y = pos.y;
		this.redraw();
	}
};
Polygon.prototype.awaitNextVertex = function() {
	var thisRef = this;
	this.onclickClosure = function(e) { thisRef.onclick.call(thisRef, e); };
	this.ondblclickClosure = function(e) { thisRef.ondblclick.call(thisRef, e); };
	this.onmousemoveClosure = function(e) { thisRef.onmousemove.call(thisRef, e); };

	// have to delay the setting of the onclick handler, otherwise IE can use it right awawy
	setTimeout(function() { top.HEURIST.registerEvent(document, "click", thisRef.onclickClosure, true); }, 0);
	top.HEURIST.registerEvent(document, "dblclick", this.ondblclickClosure, true);
	top.HEURIST.registerEvent(document, "mousemove", this.onmousemoveClosure, true);
};
Polygon.prototype.onclick = function(e) {
/*
	top.HEURIST.deregisterEvent(document, "click", this.onclickClosure, true);
	top.HEURIST.deregisterEvent(document, "mousemove", this.onmousemoveClosure, true);
*/
	this.addNewVertex();
};
Polygon.prototype.ondblclick = function(e) {
	top.HEURIST.deregisterEvent(document, "click", this.onclickClosure, true);
	top.HEURIST.deregisterEvent(document, "dblclick", this.ondblclickClosure, true);
	top.HEURIST.deregisterEvent(document, "mousemove", this.onmousemoveClosure, true);
	this.addFinalVertex();
};


Polygon.prototype.redraw = function() {
	var nPoints = 0;
	var pointsPerLine = [];

	if (this.newVertex) {
		this.minx = this.newVertex.x;
		this.miny = this.newVertex.y;
	}
	else {
		this.minx = this.vertices[0].x;
		this.miny = this.vertices[0].y;
	}

	for (var i=0; i < this.vertices.length-1; ++i) {
		var dx = this.vertices[i+1].x - this.vertices[i].x;
		var dy = this.vertices[i+1].y - this.vertices[i].y;
		var numPoints = 1 + Math.floor(Math.sqrt(dx*dx + dy*dy) / 30);
		pointsPerLine.push(numPoints);
		nPoints += numPoints;

		if (this.vertices[i].x < this.minx) this.minx = this.vertices[i].x;
		if (this.vertices[i].y < this.miny) this.miny = this.vertices[i].y;
	}
	if (this.newVertex) {
		var lastVertex = this.vertices[this.vertices.length-1];
		var dx = lastVertex.x - this.newVertex.x;
		var dy = lastVertex.y - this.newVertex.y;
		var numPoints = 1 + Math.floor(Math.sqrt(dx*dx + dy*dy) / 30);
		pointsPerLine.push(numPoints);
		nPoints += 1 + numPoints;
	}
	else {
		var lastVertex = this.vertices[this.vertices.length-1];
		var dx = lastVertex.x - this.vertices[0].x;
		var dy = lastVertex.y - this.vertices[0].y;
		var numPoints = 1 + Math.floor(Math.sqrt(dx*dx + dy*dy) / 30);
		pointsPerLine.push(numPoints);
		nPoints += numPoints;
	}

	this.allocatePoints(nPoints);

	this.minx = this.miny = 0;
	this.div.style.left = this.minx + "px";
	this.div.style.top = this.miny + "px";

	var pointsOffset = 0;
	for (var i=0; i < this.vertices.length-1; ++i) {
		var numPoints = pointsPerLine[i];
		if (! this.vertices[i+1].drawn) {
			this.drawLine(this.vertices[i], this.vertices[i+1], pointsOffset, numPoints, "point");
			this.vertices[i+1].drawn = true;
		}
		pointsOffset += numPoints;
	}

	if (this.newVertex) {
		var numPoints = pointsPerLine[this.vertices.length-1];
		this.drawLine(this.vertices[this.vertices.length-1], this.newVertex, pointsOffset, numPoints, "roving-point");
		pointsOffset += numPoints;

		var point = this.points[pointsOffset];
		point.style.left = (this.newVertex.x - this.minx) + "px";
		point.style.top = (this.newVertex.y - this.miny) + "px";
		point.className = "roving-point";
		point.style.display = "";
	}
	else {
		var numPoints = pointsPerLine[this.vertices.length-1];
		this.drawLine(this.vertices[this.vertices.length-1], this.vertices[0], pointsOffset, numPoints, "point");
	}
};
Polygon.prototype.drawLine = function(v1, v2, offset, numPoints, className) {
	for (var i=0; i < numPoints; ++i) {
		var frac = i / numPoints;
		var x = Math.round(v2.x*frac + v1.x*(1 - frac)) - this.minx;
		var y = Math.round(v2.y*frac + v1.y*(1 - frac)) - this.miny;

		var point = this.points[offset+i];
		point.className = className;
		point.style.left = x + "px";
		point.style.top = y + "px";
		point.style.display = "";
	}
};




top.HEURIST = {};
top.HEURIST.registerEvent = function(element, eventType, fn, capture, priority) {
	if (window.addEventListener) {
		element.addEventListener(eventType, fn, capture);
	} else if (window.attachEvent) {
		element.attachEvent("on" + eventType, fn);
	}
};
top.HEURIST.deregisterEvent = function(element, eventType, fn, capture) {
	if (window.removeEventListener) {
		element.removeEventListener(eventType, fn, capture);
	} else if (window.detachEvent) {
		element.detachEvent("on" + eventType, fn);
	}
};
top.HEURIST.util = {};
top.HEURIST.util.getEventPosition = function(evt) {
                // return the coordinates of the given event relative to the document
                var x = 0, y = 0;
                if (evt.pageX  ||  evt.pageY) {
                        x = evt.pageX;
                        y = evt.pageY;
                } else if (evt.clientX  ||  evt.clientY) {
                        x = evt.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
                        y = evt.clientY + document.body.scrollTop + document.documentElement.scrollTop;
                }

                return { x: x, y: y };
};


</script>


    <script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAAWXRbJ6-0zaNuAoz9XBmHZRR-LdPXEsKewYGCwjvMXFkd70PDCxRPI1APacD5QLZskqrCkKP5egAuPA"
      type="text/javascript"></script>
    <script type="text/javascript">

    //<![CDATA[

    var map;
    var polyShape;
    var polygonMode;
    var polygonDepth = "20";
    var polyPoints = [];
    var marker;
    var geocoder = null;

    var fillColor = "#0000FF"; // blue fill
    var lineColor = "#000000"; // black line
    var opacity = .5;
    var lineWeight = 2;

    var pointIcon;

    function load() {
      if (GBrowserIsCompatible()) {
        map = new GMap2(document.getElementById("map"));
	map.enableDoubleClickZoom();
	map.enableContinuousZoom();
	map.enableScrollWheelZoom();
	map.addControl(new GSmallMapControl());
        map.setCenter(new GLatLng(0, 0), 1);

	window.shape = {
		type: "circle",
		centre: new GLatLng(10, 10),
		radius: 4
	};


	var centrePos = window.shape.centre;
	window.shape.centreMarker = new GMarker(centrePos, { bouncy: true, draggable: true });
	GEvent.addListener(window.shape.centreMarker, "dragend", function() {
		var rpoint = window.shape.radiusMarker.getPoint();
		var cpoint = window.shape.centreMarker.getPoint();
		var dy = cpoint.lat() - window.shape.centre.lat();
		var dx = cpoint.lng() - window.shape.centre.lng();

		window.shape.centre = cpoint;
		window.shape.radiusMarker.setPoint(new GLatLng(rpoint.lat()+dy, rpoint.lng()+dx));
		drawCircle();
	});
	map.addOverlay(window.shape.centreMarker);

	var radiusIcon = new GIcon();
	radiusIcon.image = "triangle.png";
	radiusIcon.shadow = "triangle-shadow.png";
	radiusIcon.iconSize = new GSize(21, 19);
	radiusIcon.shadowSize = new GSize(42, 19);
	radiusIcon.iconAnchor = new GPoint(10, 18);

	var radiusPos = new GLatLng(centrePos.lat() - window.shape.radius/Math.sqrt(2), centrePos.lng() + window.shape.radius/Math.sqrt(2));
	window.shape.radiusMarker = new GMarker(radiusPos, { icon: radiusIcon, bouncy: false, draggable: true });
	GEvent.addListener(window.shape.radiusMarker, "drag", function() {
		var rpoint = window.shape.radiusMarker.getPoint();
		var dy = rpoint.lat() - window.shape.centre.lat();
		var dx = rpoint.lng() - window.shape.centre.lng();
		window.shape.radius = Math.sqrt(dx*dx + dy*dy);
		drawCircle();
	});
	map.addOverlay(window.shape.radiusMarker);

	drawCircle();
      }
    }


function drawCircle() {
	if (window.shape.circlePolyline) map.removeOverlay(window.shape.circlePolyline);

	var centre = window.shape.centre;
	var radius = window.shape.radius;
	var points = [];
	for (var i=0; i < 30; ++i) {
		var P = new GLatLng(centre.lat() + (radius * Math.sin(2 * Math.PI * i / 30)),
		                    centre.lng() + (radius * Math.cos(2 * Math.PI * i / 30)));
		points.push(P);
	}
	points.push(points[0]);	// close the circle

	window.shape.circlePolyline = new GPolyline(points, "blue", 4, 0.8);
	map.addOverlay(window.shape.circlePolyline);
}


function mapClick(marker, clickedPoint) {
	polygonMode = document.getElementById("drawMode_polygon").checked;
	oldMarker = marker;

	polyPoints.push(clickedPoint);
	drawCoordinates();
}

function drawCoordinates() {
	if (polygonMode) {
		polyShape = new GPolygon(polyPoints, lineColor, lineWeight, fillColor, opacity);
	}
	else {
		polyShape = new GPolyline(polyPoints, lineColor, lineWeight, opacity);
	}

	map.clearOverlays();

	marker = new GMarker(polyPoints[polyPoints.length-1]);
	map.addOverlay(marker);
	map.addOverlay(polyShape);
}

function clearMap(){
  map.clearOverlays();

  polyPoints = [];
  document.getElementById("coords").value =  "&lt;-- Click on the map to digitize!";
}

function deleteLastPoint(){
  map.removeOverlay(polyShape);
  // pop last element of polypoint array
  polyPoints.pop();
  drawCoordinates();
}

    //]]>
    </script>
  </head>
  <body onload="load()" onunload="GUnload()">
    <div id="map" style="width: 600px; height: 300px"></div>
    <label for=drawMode_polygon><input type=radio name=mode id=drawMode_polygon checked> polygon</label>
    <label for=drawMode_polyline><input type=radio name=mode id=drawMode_polyline checked> polyline</label>
  </body>
</html>


</body>
</html>
